Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Node / ReticulumProjects / MeshChatX.git / files / scripts / build-android-wheels-local.sh

Displaying Raw • Download


scripts/build-android-wheels-local.sh a6764d3d38e8710c5352bbfe4024dbb36c3a48a2 (a6764d3d) Text, 26.92 KB

T8b949e#!/usr/bin/env bash
Tffa657set -euo pipefail

usageTff7b72(Tff7b72) Tff7b72{
cat Ta5d6ff<<'EOF'
Build Android wheels locally for Chaquopy (Linux x86_64 host).

This script:
1) Clones/updates Chaquopy sources locally
2) Downloads a matching Chaquopy Python target toolchain
3) Builds pycodec2 Android wheels with Chaquopy's build-wheel tool
4) Optionally patches LXST wheel metadata for local Android constraints
5) Builds every recipe under android/chaquopy-recipes/ for each requested
ABI (currently: cryptography, miniaudio)
6) Copies outputs to android/vendor

Usage:
scripts/build-android-wheels-local.sh [options]

Options:
--python-minor X.Y Python minor for target wheels (default: 3.11)
--target-version V Explicit Chaquopy target version (default: auto latest for python minor)
--chaquopy-ref REF Chaquopy git ref/commit to checkout (default: master)
--abis LIST Comma-separated ABIs (default: arm64-v8a,x86_64,armeabi-v7a)
--api-level N Android API level for wheel tag (default: 24)
--pycodec2-version V pycodec2 version to build (default: 4.1.1)
--numpy-version V NumPy version used during pycodec2 build (default: 1.26.2)
--lxst-version V LXST wheel version for metadata patch (default: 0.4.6)
--no-lxst-patch Skip LXST metadata patch
--only-recipes LIST Comma-separated recipe directory names under
android/chaquopy-recipes to build. When set, the
NumPy, pycodec2/chaquopy-libcodec2 and LXST steps
are skipped and only matching custom recipes run.
--work-dir PATH Working directory (default: ./.local/chaquopy-build-wheel)
--out-dir PATH Output wheel directory (default: ./android/vendor)
-h, --help Show this help
EOF
Tff7b72}

Te6edf3ROOT_DIRTff7b72=Ta5d6ff"Tff7b72$(Tffa657cd Ta5d6ff"Tff7b72$(dirname Ta5d6ff"Tffd700${Te6edf3BASH_SOURCETb4b4b4[0]Tffd700}Ta5d6ff"Tff7b72)Ta5d6ff/..Ta5d6ff" Tff7b72&& Tffa657pwdTff7b72)Ta5d6ff"

Te6edf3PYTHON_MINORTff7b72=Ta5d6ff"3.11"
Te6edf3TARGET_VERSIONTff7b72=Ta5d6ff""
Te6edf3CHAQUOPY_REFTff7b72=Ta5d6ff"Tffd700${Te6edf3CHAQUOPY_REFTff7b72:-Te6edf3masterTffd700}Ta5d6ff"
Te6edf3ABI_LISTTff7b72=Ta5d6ff"arm64-v8a,x86_64,armeabi-v7a"
Te6edf3API_LEVELTff7b72=Ta5d6ff"24"
Te6edf3PYCODEC2_VERSIONTff7b72=Ta5d6ff"4.1.1"
Te6edf3LIBCODEC2_VERSIONTff7b72=Ta5d6ff"1.2.0"
Te6edf3NUMPY_VERSIONTff7b72=Ta5d6ff"1.26.2"
Te6edf3LXST_VERSIONTff7b72=Ta5d6ff"0.4.6"
Te6edf3PATCH_LXSTTff7b72=Ta5d6ff"1"
Te6edf3ONLY_RECIPESTff7b72=Ta5d6ff""
Te6edf3WORK_DIRTff7b72=Ta5d6ff"Tffd700${Te6edf3ROOT_DIRTffd700}Ta5d6ff/.local/chaquopy-build-wheelTa5d6ff"
Te6edf3OUT_DIRTff7b72=Ta5d6ff"Tffd700${Te6edf3ROOT_DIRTffd700}Ta5d6ff/android/vendorTa5d6ff"

Tff7b72while Tff7b72[Tff7b72[ Te6edf3$# -gt T79c0ff0 Tff7b72]Tff7b72]Tb4b4b4; Tff7b72do
Tff7b72case Ta5d6ff"Te6edf3$1Ta5d6ff" Tff7b72in
--python-minorTff7b72)
Te6edf3PYTHON_MINORTff7b72=Ta5d6ff"Tffd700${Te6edf32Tb4b4b4:Tb4b4b4?missing value for --python-minorTffd700}Ta5d6ff"
Tffa657shift T79c0ff2
Tb4b4b4;Tb4b4b4;
--target-versionTff7b72)
Te6edf3TARGET_VERSIONTff7b72=Ta5d6ff"Tffd700${Te6edf32Tb4b4b4:Tb4b4b4?missing value for --target-versionTffd700}Ta5d6ff"
Tffa657shift T79c0ff2
Tb4b4b4;Tb4b4b4;
--chaquopy-refTff7b72)
Te6edf3CHAQUOPY_REFTff7b72=Ta5d6ff"Tffd700${Te6edf32Tb4b4b4:Tb4b4b4?missing value for --chaquopy-refTffd700}Ta5d6ff"
Tffa657shift T79c0ff2
Tb4b4b4;Tb4b4b4;
--abisTff7b72)
Te6edf3ABI_LISTTff7b72=Ta5d6ff"Tffd700${Te6edf32Tb4b4b4:Tb4b4b4?missing value for --abisTffd700}Ta5d6ff"
Tffa657shift T79c0ff2
Tb4b4b4;Tb4b4b4;
--api-levelTff7b72)
Te6edf3API_LEVELTff7b72=Ta5d6ff"Tffd700${Te6edf32Tb4b4b4:Tb4b4b4?missing value for --api-levelTffd700}Ta5d6ff"
Tffa657shift T79c0ff2
Tb4b4b4;Tb4b4b4;
--pycodec2-versionTff7b72)
Te6edf3PYCODEC2_VERSIONTff7b72=Ta5d6ff"Tffd700${Te6edf32Tb4b4b4:Tb4b4b4?missing value for --pycodec2-versionTffd700}Ta5d6ff"
Tffa657shift T79c0ff2
Tb4b4b4;Tb4b4b4;
--numpy-versionTff7b72)
Te6edf3NUMPY_VERSIONTff7b72=Ta5d6ff"Tffd700${Te6edf32Tb4b4b4:Tb4b4b4?missing value for --numpy-versionTffd700}Ta5d6ff"
Tffa657shift T79c0ff2
Tb4b4b4;Tb4b4b4;
--lxst-versionTff7b72)
Te6edf3LXST_VERSIONTff7b72=Ta5d6ff"Tffd700${Te6edf32Tb4b4b4:Tb4b4b4?missing value for --lxst-versionTffd700}Ta5d6ff"
Tffa657shift T79c0ff2
Tb4b4b4;Tb4b4b4;
--no-lxst-patchTff7b72)
Te6edf3PATCH_LXSTTff7b72=Ta5d6ff"0"
Tffa657shift
Tb4b4b4;Tb4b4b4;
--only-recipesTff7b72)
Te6edf3ONLY_RECIPESTff7b72=Ta5d6ff"Tffd700${Te6edf32Tb4b4b4:Tb4b4b4?missing value for --only-recipesTffd700}Ta5d6ff"
Tffa657shift T79c0ff2
Tb4b4b4;Tb4b4b4;
--work-dirTff7b72)
Te6edf3WORK_DIRTff7b72=Ta5d6ff"Tffd700${Te6edf32Tb4b4b4:Tb4b4b4?missing value for --work-dirTffd700}Ta5d6ff"
Tffa657shift T79c0ff2
Tb4b4b4;Tb4b4b4;
--out-dirTff7b72)
Te6edf3OUT_DIRTff7b72=Ta5d6ff"Tffd700${Te6edf32Tb4b4b4:Tb4b4b4?missing value for --out-dirTffd700}Ta5d6ff"
Tffa657shift T79c0ff2
Tb4b4b4;Tb4b4b4;
-hTb4b4b4|--helpTff7b72)
usage
Tffa657exit T79c0ff0
Tb4b4b4;Tb4b4b4;
*Tff7b72)
Tffa657echo Ta5d6ff"Ta5d6ffUnknown argument: Te6edf3$1Ta5d6ff" >Tb4b4b4&T79c0ff2
usage
Tffa657exit T79c0ff1
Tb4b4b4;Tb4b4b4;
Tff7b72esac
Tff7b72done

require_cmdTff7b72(Tff7b72) Tff7b72{
Tff7b72if ! Tffa657command -v Ta5d6ff"Te6edf3$1Ta5d6ff" >/dev/null T79c0ff2>Tb4b4b4&T79c0ff1Tb4b4b4; Tff7b72then
Tffa657echo Ta5d6ff"Ta5d6ffMissing required command: Te6edf3$1Ta5d6ff" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72fi
Tff7b72}

abi_to_platform_tagTff7b72(Tff7b72) Tff7b72{
Tff7b72case Ta5d6ff"Te6edf3$1Ta5d6ff" Tff7b72in
arm64-v8aTff7b72) Tffa657echo Ta5d6ff"android_21_arm64_v8a" Tb4b4b4;Tb4b4b4;
x86_64Tff7b72) Tffa657echo Ta5d6ff"android_21_x86_64" Tb4b4b4;Tb4b4b4;
armeabi-v7aTff7b72) Tffa657echo Ta5d6ff"android_16_armeabi_v7a" Tb4b4b4;Tb4b4b4;
x86Tff7b72) Tffa657echo Ta5d6ff"android_16_x86" Tb4b4b4;Tb4b4b4;
*Tff7b72)
Tffa657echo Ta5d6ff"Ta5d6ffUnsupported ABI: Te6edf3$1Ta5d6ff" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tb4b4b4;Tb4b4b4;
Tff7b72esac
Tff7b72}

discover_latest_targetTff7b72(Tff7b72) Tff7b72{
Tffa657local Te6edf3python_minorTff7b72=Ta5d6ff"Te6edf3$1Ta5d6ff"
Tffa657local metadata versions latest
Te6edf3metadataTff7b72=Ta5d6ff"Tff7b72$(curl -fsSL Ta5d6ff"https://repo.maven.apache.org/maven2/com/chaquo/python/target/maven-metadata.xml"Tff7b72)Ta5d6ff"
Te6edf3versionsTff7b72=Ta5d6ff"Tff7b72$(Tffa657printf Ta5d6ff'%s\n' Ta5d6ff"Te6edf3$metadataTa5d6ff" Tffea00\
Tb4b4b4| sed -n Ta5d6ff's|.*<version>\(.*\)</version>.*|\1|p' Tffea00\
Tb4b4b4| awk -v Te6edf3pTff7b72=Ta5d6ff"Tffd700${Te6edf3python_minorTffd700}Ta5d6ff.Ta5d6ff" Ta5d6ff'index($0, p)==1'Tff7b72)Ta5d6ff"
Te6edf3latestTff7b72=Ta5d6ff"Tff7b72$(Tffa657printf Ta5d6ff'%s\n' Ta5d6ff"Te6edf3$versionsTa5d6ff" Tb4b4b4| sort -V Tb4b4b4| tail -n T79c0ff1Tff7b72)Ta5d6ff"
Tff7b72if Tff7b72[Tff7b72[ -z Ta5d6ff"Tffd700${Te6edf3latestTffd700}Ta5d6ff" Tff7b72]Tff7b72]Tb4b4b4; Tff7b72then
Tffa657echo Ta5d6ff"Ta5d6ffCould not discover Chaquopy target version for Python Tffd700${Te6edf3python_minorTffd700}Ta5d6ff" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72fi
Tffa657printf Ta5d6ff'%s\n' Ta5d6ff"Te6edf3$latestTa5d6ff"
Tff7b72}

require_cmd git
require_cmd curl
require_cmd sed
require_cmd awk
require_cmd sort

Tff7b72case Ta5d6ff"Ta5d6ff,Tffd700${Te6edf3ABI_LISTTffd700}Ta5d6ff,Ta5d6ff" Tff7b72in
*,armeabi-v7a,*Tff7b72)
Tff7b72if Tff7b72[Tff7b72[ -z Ta5d6ff"Tffd700${Te6edf3ONLY_RECIPESTffd700}Ta5d6ff" Tff7b72]Tff7b72]Tb4b4b4; Tff7b72then
Tff7b72if Tff7b72[Tff7b72[ -z Ta5d6ff"Tffd700${Te6edf3ANDROID_HOMETff7b72:-Tffd700}Ta5d6ff" Tff7b72&& -z Ta5d6ff"Tffd700${Te6edf3ANDROID_SDK_ROOTTff7b72:-Tffd700}Ta5d6ff" Tff7b72]Tff7b72]Tb4b4b4; Tff7b72then
Tffa657echo Ta5d6ff"armeabi-v7a: NumPy is built from source and needs the Android SDK/NDK (Chaquopy android-env.sh)." >Tb4b4b4&T79c0ff2
Tffa657echo Ta5d6ff"Set ANDROID_HOME or ANDROID_SDK_ROOT to your SDK root (with cmdline-tools/latest/bin/sdkmanager)." >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72fi
Tffa657export Te6edf3ANDROID_HOMETff7b72=Ta5d6ff"Tffd700${Te6edf3ANDROID_HOMETff7b72:-Tffd700${Te6edf3ANDROID_SDK_ROOTTffd700}Tffd700}Ta5d6ff"
Tffa657export Te6edf3ANDROID_SDK_ROOTTff7b72=Ta5d6ff"Tffd700${Te6edf3ANDROID_SDK_ROOTTff7b72:-Tffd700${Te6edf3ANDROID_HOMETffd700}Tffd700}Ta5d6ff"
Tff7b72if Tff7b72[Tff7b72[ ! -x Ta5d6ff"Tffd700${Te6edf3ANDROID_HOMETffd700}Ta5d6ff/cmdline-tools/latest/bin/sdkmanagerTa5d6ff" Tff7b72]Tff7b72]Tb4b4b4; Tff7b72then
Tffa657echo Ta5d6ff"Ta5d6ffarmeabi-v7a: expected sdkmanager at Tffd700${Te6edf3ANDROID_HOMETffd700}Ta5d6ff/cmdline-tools/latest/bin/sdkmanagerTa5d6ff" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72fi
Tff7b72else
Tffa657export Te6edf3ANDROID_HOMETff7b72=Ta5d6ff"Tffd700${Te6edf3ANDROID_HOMETff7b72:-Tffd700${Te6edf3ANDROID_SDK_ROOTTff7b72:-Tffd700}Tffd700}Ta5d6ff"
Tffa657export Te6edf3ANDROID_SDK_ROOTTff7b72=Ta5d6ff"Tffd700${Te6edf3ANDROID_SDK_ROOTTff7b72:-Tffd700${Te6edf3ANDROID_HOMETff7b72:-Tffd700}Tffd700}Ta5d6ff"
Tff7b72fi
Tb4b4b4;Tb4b4b4;
Tff7b72esac

Te6edf3PYTHON_BINTff7b72=Ta5d6ff"Tffd700${Te6edf3PYTHON_BINTff7b72:-Te6edf3pythonTffd700${Te6edf3PYTHON_MINORTffd700}Tffd700}Ta5d6ff"
Tff7b72if ! Tffa657command -v Ta5d6ff"Tffd700${Te6edf3PYTHON_BINTffd700}Ta5d6ff" >/dev/null T79c0ff2>Tb4b4b4&T79c0ff1Tb4b4b4; Tff7b72then
Tffa657echo Ta5d6ff"Ta5d6ffRequired interpreter not found: Tffd700${Te6edf3PYTHON_BINTffd700}Ta5d6ff" >Tb4b4b4&T79c0ff2
Tffa657echo Ta5d6ff"Ta5d6ffInstall Python Tffd700${Te6edf3PYTHON_MINORTffd700}Ta5d6ff (e.g. uv python install Tffd700${Te6edf3PYTHON_MINORTffd700}Ta5d6ff) or set PYTHON_BIN.Ta5d6ff" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72fi

mkdir -p Ta5d6ff"Tffd700${Te6edf3WORK_DIRTffd700}Ta5d6ff" Ta5d6ff"Tffd700${Te6edf3OUT_DIRTffd700}Ta5d6ff"

Te6edf3CHAQUOPY_DIRTff7b72=Ta5d6ff"Tffd700${Te6edf3WORK_DIRTffd700}Ta5d6ff/chaquopyTa5d6ff"
Tff7b72if Tff7b72[Tff7b72[ ! -d Ta5d6ff"Tffd700${Te6edf3CHAQUOPY_DIRTffd700}Ta5d6ff/.gitTa5d6ff" Tff7b72]Tff7b72]Tb4b4b4; Tff7b72then
git clone --depth T79c0ff1 https://github.com/chaquo/chaquopy.git Ta5d6ff"Tffd700${Te6edf3CHAQUOPY_DIRTffd700}Ta5d6ff"
Tff7b72fi
git -C Ta5d6ff"Tffd700${Te6edf3CHAQUOPY_DIRTffd700}Ta5d6ff" fetch --depth T79c0ff1 origin Ta5d6ff"Tffd700${Te6edf3CHAQUOPY_REFTffd700}Ta5d6ff"
git -C Ta5d6ff"Tffd700${Te6edf3CHAQUOPY_DIRTffd700}Ta5d6ff" checkout --detach FETCH_HEAD

Tff7b72if Tff7b72[Tff7b72[ -z Ta5d6ff"Tffd700${Te6edf3TARGET_VERSIONTffd700}Ta5d6ff" Tff7b72]Tff7b72]Tb4b4b4; Tff7b72then
Te6edf3TARGET_VERSIONTff7b72=Ta5d6ff"Tff7b72$(discover_latest_target Ta5d6ff"Tffd700${Te6edf3PYTHON_MINORTffd700}Ta5d6ff"Tff7b72)Ta5d6ff"
Tff7b72fi
Tffa657echo Ta5d6ff"Ta5d6ffUsing Chaquopy git ref: Tffd700${Te6edf3CHAQUOPY_REFTffd700}Ta5d6ff"
Tffa657echo Ta5d6ff"Ta5d6ffUsing Chaquopy target version: Tffd700${Te6edf3TARGET_VERSIONTffd700}Ta5d6ff"

Tffa657pushd Ta5d6ff"Tffd700${Te6edf3CHAQUOPY_DIRTffd700}Ta5d6ff" >/dev/null
Te6edf3TARGET_PATHTff7b72=Ta5d6ff"Ta5d6ffmaven/com/chaquo/python/target/Tffd700${Te6edf3TARGET_VERSIONTffd700}Ta5d6ff"
Tff7b72if Tff7b72[Tff7b72[ ! -d Ta5d6ff"Tffd700${Te6edf3TARGET_PATHTffd700}Ta5d6ff" Tff7b72]Tff7b72]Tb4b4b4; Tff7b72then
./target/download-target.sh Ta5d6ff"Tffd700${Te6edf3TARGET_PATHTffd700}Ta5d6ff"
Tff7b72else
Tffa657echo Ta5d6ff"Ta5d6ffChaquopy target already present: Tffd700${Te6edf3TARGET_PATHTffd700}Ta5d6ff"
Tff7b72fi
Tffa657popd >/dev/null

Te6edf3PYPIDIRTff7b72=Ta5d6ff"Tffd700${Te6edf3CHAQUOPY_DIRTffd700}Ta5d6ff/server/pypiTa5d6ff"
Te6edf3VENV_DIRTff7b72=Ta5d6ff"Tffd700${Te6edf3PYPIDIRTffd700}Ta5d6ff/.venv-localTa5d6ff"
rm -rf Ta5d6ff"Tffd700${Te6edf3VENV_DIRTffd700}Ta5d6ff"
Ta5d6ff"Tffd700${Te6edf3PYTHON_BINTffd700}Ta5d6ff" -m venv Ta5d6ff"Tffd700${Te6edf3VENV_DIRTffd700}Ta5d6ff"
T8b949e# Some Python images only provide python3/python3.X in venv bin, while the
T8b949e# script below invokes `${VENV_DIR}/bin/python`.
Tff7b72if Tff7b72[Tff7b72[ ! -e Ta5d6ff"Tffd700${Te6edf3VENV_DIRTffd700}Ta5d6ff/bin/pythonTa5d6ff" Tff7b72&& -e Ta5d6ff"Tffd700${Te6edf3VENV_DIRTffd700}Ta5d6ff/bin/python3Ta5d6ff" Tff7b72]Tff7b72]Tb4b4b4; Tff7b72then
ln -sf python3 Ta5d6ff"Tffd700${Te6edf3VENV_DIRTffd700}Ta5d6ff/bin/pythonTa5d6ff"
Tff7b72fi
Ta5d6ff"Tffd700${Te6edf3VENV_DIRTffd700}Ta5d6ff/bin/pipTa5d6ff" install --upgrade pip
Ta5d6ff"Tffd700${Te6edf3VENV_DIRTffd700}Ta5d6ff/bin/pipTa5d6ff" install -r Ta5d6ff"Tffd700${Te6edf3PYPIDIRTffd700}Ta5d6ff/requirements.txtTa5d6ff"
Ta5d6ff"Tffd700${Te6edf3VENV_DIRTffd700}Ta5d6ff/bin/pipTa5d6ff" install Ta5d6ff"Ta5d6ffnumpy==Tffd700${Te6edf3NUMPY_VERSIONTffd700}Ta5d6ff"
T8b949e# Chaquopy build-wheel.py shells out to `wheel pack`, so ensure the venv scripts are first on PATH.
Tffa657export Te6edf3PATHTff7b72=Ta5d6ff"Tffd700${Te6edf3VENV_DIRTffd700}Ta5d6ff/bin:Tffd700${Te6edf3PATHTffd700}Ta5d6ff"
Tff7b72if ! Tffa657command -v wheel >/dev/null T79c0ff2>Tb4b4b4&T79c0ff1Tb4b4b4; Tff7b72then
Tffa657echo Ta5d6ff"Ta5d6ffMissing required wheel CLI in virtualenv at Tffd700${Te6edf3VENV_DIRTffd700}Ta5d6ff" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72fi

Te6edf3NUMPY_DIST_DIRTff7b72=Ta5d6ff"Tffd700${Te6edf3PYPIDIRTffd700}Ta5d6ff/dist/numpyTa5d6ff"
mkdir -p Ta5d6ff"Tffd700${Te6edf3NUMPY_DIST_DIRTffd700}Ta5d6ff"
Te6edf3PYTHON_ABI_TAGTff7b72=Ta5d6ff"Ta5d6ffcpTffd700${Te6edf3PYTHON_MINORTb4b4b4/./Tffd700}Ta5d6ff"

T8b949e# Chaquopy's numpy recipe lists chaquopy-openblas as a host requirement. build-wheel.py
T8b949e# only loads it from ${PYPIDIR}/dist/chaquopy-openblas/ (it does not fetch from the index).
T8b949e# Official wheels: https://chaquo.com/pypi-13.1/chaquopy-openblas/
cache_chaquopy_openblas_for_abiTff7b72(Tff7b72) Tff7b72{
Tffa657local Te6edf3abiTff7b72=Ta5d6ff"Te6edf3$1Ta5d6ff"
Tffa657local name url
mkdir -p Ta5d6ff"Tffd700${Te6edf3PYPIDIRTffd700}Ta5d6ff/dist/chaquopy-openblasTa5d6ff"
Tff7b72case Ta5d6ff"Tffd700${Te6edf3abiTffd700}Ta5d6ff" Tff7b72in
armeabi-v7aTff7b72) Te6edf3nameTff7b72=Ta5d6ff"chaquopy_openblas-0.2.20-5-py3-none-android_16_armeabi_v7a.whl" Tb4b4b4;Tb4b4b4;
arm64-v8aTff7b72) Te6edf3nameTff7b72=Ta5d6ff"chaquopy_openblas-0.2.20-5-py3-none-android_21_arm64_v8a.whl" Tb4b4b4;Tb4b4b4;
x86_64Tff7b72) Te6edf3nameTff7b72=Ta5d6ff"chaquopy_openblas-0.2.20-5-py3-none-android_21_x86_64.whl" Tb4b4b4;Tb4b4b4;
*Tff7b72) Tff7b72return T79c0ff0 Tb4b4b4;Tb4b4b4;
Tff7b72esac
Te6edf3urlTff7b72=Ta5d6ff"Ta5d6ffhttps://chaquo.com/pypi-13.1/chaquopy-openblas/Tffd700${Te6edf3nameTffd700}Ta5d6ff"
Tff7b72if Tff7b72[Tff7b72[ -f Ta5d6ff"Tffd700${Te6edf3PYPIDIRTffd700}Ta5d6ff/dist/chaquopy-openblas/Tffd700${Te6edf3nameTffd700}Ta5d6ff" Tff7b72]Tff7b72]Tb4b4b4; Tff7b72then
Tff7b72return T79c0ff0
Tff7b72fi
Tffa657echo Ta5d6ff"Ta5d6ffCaching Chaquopy OpenBLAS wheel for Tffd700${Te6edf3abiTffd700}Ta5d6ff"
curl -fsSL -o Ta5d6ff"Tffd700${Te6edf3PYPIDIRTffd700}Ta5d6ff/dist/chaquopy-openblas/Tffd700${Te6edf3nameTffd700}Ta5d6ff" Ta5d6ff"Tffd700${Te6edf3urlTffd700}Ta5d6ff"
Tff7b72}

cache_chaquopy_libffi_for_abiTff7b72(Tff7b72) Tff7b72{
Tffa657local Te6edf3abiTff7b72=Ta5d6ff"Te6edf3$1Ta5d6ff"
Tffa657local name url
mkdir -p Ta5d6ff"Tffd700${Te6edf3PYPIDIRTffd700}Ta5d6ff/dist/chaquopy-libffiTa5d6ff"
Tff7b72case Ta5d6ff"Tffd700${Te6edf3abiTffd700}Ta5d6ff" Tff7b72in
armeabi-v7aTff7b72) Te6edf3nameTff7b72=Ta5d6ff"chaquopy_libffi-3.3-2-py3-none-android_16_armeabi_v7a.whl" Tb4b4b4;Tb4b4b4;
arm64-v8aTff7b72) Te6edf3nameTff7b72=Ta5d6ff"chaquopy_libffi-3.3-3-py3-none-android_24_arm64_v8a.whl" Tb4b4b4;Tb4b4b4;
x86_64Tff7b72) Te6edf3nameTff7b72=Ta5d6ff"chaquopy_libffi-3.3-3-py3-none-android_24_x86_64.whl" Tb4b4b4;Tb4b4b4;
*Tff7b72) Tff7b72return T79c0ff0 Tb4b4b4;Tb4b4b4;
Tff7b72esac
Te6edf3urlTff7b72=Ta5d6ff"Ta5d6ffhttps://chaquo.com/pypi-13.1/chaquopy-libffi/Tffd700${Te6edf3nameTffd700}Ta5d6ff"
Tff7b72if Tff7b72[Tff7b72[ -f Ta5d6ff"Tffd700${Te6edf3PYPIDIRTffd700}Ta5d6ff/dist/chaquopy-libffi/Tffd700${Te6edf3nameTffd700}Ta5d6ff" Tff7b72]Tff7b72]Tb4b4b4; Tff7b72then
Tff7b72return T79c0ff0
Tff7b72fi
Tffa657echo Ta5d6ff"Ta5d6ffCaching Chaquopy libffi wheel for Tffd700${Te6edf3abiTffd700}Ta5d6ff"
curl -fsSL -o Ta5d6ff"Tffd700${Te6edf3PYPIDIRTffd700}Ta5d6ff/dist/chaquopy-libffi/Tffd700${Te6edf3nameTffd700}Ta5d6ff" Ta5d6ff"Tffd700${Te6edf3urlTffd700}Ta5d6ff"
Tff7b72}

Tff7b72if Tff7b72[Tff7b72[ -z Ta5d6ff"Tffd700${Te6edf3ONLY_RECIPESTffd700}Ta5d6ff" Tff7b72]Tff7b72]Tb4b4b4; Tff7b72then
Tff7b72for abi Tff7b72in Tffd700${Te6edf3ABI_LISTTb4b4b4//,/ Tffd700}Tb4b4b4; Tff7b72do
Te6edf3platform_tagTff7b72=Ta5d6ff"Tff7b72$(abi_to_platform_tag Ta5d6ff"Tffd700${Te6edf3abiTffd700}Ta5d6ff"Tff7b72)Ta5d6ff"
Tffa657echo Ta5d6ff"Ta5d6ffResolving NumPy wheel for ABI Tffd700${Te6edf3abiTffd700}Ta5d6ff (Tffd700${Te6edf3platform_tagTffd700}Ta5d6ff)Ta5d6ff"
Tff7b72if ! Ta5d6ff"Tffd700${Te6edf3VENV_DIRTffd700}Ta5d6ff/bin/pipTa5d6ff" download Tffea00\
--only-binaryTff7b72=:all: Tffea00\
--no-deps Tffea00\
--platform Ta5d6ff"Tffd700${Te6edf3platform_tagTffd700}Ta5d6ff" Tffea00\
--python-version Ta5d6ff"Tffd700${Te6edf3PYTHON_MINORTb4b4b4/./Tffd700}Ta5d6ff" Tffea00\
--implementation cp Tffea00\
--abi Ta5d6ff"Tffd700${Te6edf3PYTHON_ABI_TAGTffd700}Ta5d6ff" Tffea00\
Ta5d6ff"Ta5d6ffnumpy==Tffd700${Te6edf3NUMPY_VERSIONTffd700}Ta5d6ff" Tffea00\
--index-url https://pypi.org/simple Tffea00\
--extra-index-url https://chaquo.com/pypi-13.1 Tffea00\
--dest Ta5d6ff"Tffd700${Te6edf3NUMPY_DIST_DIRTffd700}Ta5d6ff"Tb4b4b4; Tff7b72then
Tffa657echo Ta5d6ff"Ta5d6ffNo prebuilt NumPy wheel for Tffd700${Te6edf3abiTffd700}Ta5d6ff; building locally via Chaquopy recipeTa5d6ff"
cache_chaquopy_openblas_for_abi Ta5d6ff"Tffd700${Te6edf3abiTffd700}Ta5d6ff"
Ta5d6ff"Tffd700${Te6edf3VENV_DIRTffd700}Ta5d6ff/bin/pythonTa5d6ff" Ta5d6ff"Tffd700${Te6edf3PYPIDIRTffd700}Ta5d6ff/build-wheel.pyTa5d6ff" Tffea00\
--python Ta5d6ff"Tffd700${Te6edf3PYTHON_MINORTffd700}Ta5d6ff" Tffea00\
--api-level Ta5d6ff"Tffd700${Te6edf3API_LEVELTffd700}Ta5d6ff" Tffea00\
--abi Ta5d6ff"Tffd700${Te6edf3abiTffd700}Ta5d6ff" Tffea00\
Ta5d6ff"Tffd700${Te6edf3PYPIDIRTffd700}Ta5d6ff/packages/numpyTa5d6ff"
Tff7b72fi
Tff7b72done
Tff7b72else
Tffa657echo Ta5d6ff"Skipping NumPy wheel resolution (--only-recipes set)"
Tff7b72fi

Tff7b72if Tff7b72[Tff7b72[ -z Ta5d6ff"Tffd700${Te6edf3ONLY_RECIPESTffd700}Ta5d6ff" Tff7b72]Tff7b72]Tb4b4b4; Tff7b72then

Te6edf3RECIPE_DIRTff7b72=Ta5d6ff"Tffd700${Te6edf3WORK_DIRTffd700}Ta5d6ff/recipes/pycodec2-localTa5d6ff"
Te6edf3LIBCODEC2_RECIPE_DIRTff7b72=Ta5d6ff"Tffd700${Te6edf3WORK_DIRTffd700}Ta5d6ff/recipes/chaquopy-libcodec2-localTa5d6ff"
Te6edf3SOURCE_DIRTff7b72=Ta5d6ff"Tffd700${Te6edf3WORK_DIRTffd700}Ta5d6ff/sources/pycodec2-Tffd700${Te6edf3PYCODEC2_VERSIONTffd700}Ta5d6ff"
rm -rf Ta5d6ff"Tffd700${Te6edf3RECIPE_DIRTffd700}Ta5d6ff" Ta5d6ff"Tffd700${Te6edf3LIBCODEC2_RECIPE_DIRTffd700}Ta5d6ff"
mkdir -p Ta5d6ff"Tffd700${Te6edf3RECIPE_DIRTffd700}Ta5d6ff" Ta5d6ff"Tffd700${Te6edf3LIBCODEC2_RECIPE_DIRTffd700}Ta5d6ff" Ta5d6ff"Tffd700${Te6edf3WORK_DIRTffd700}Ta5d6ff/sourcesTa5d6ff"

rm -rf Ta5d6ff"Tffd700${Te6edf3SOURCE_DIRTffd700}Ta5d6ff"
Ta5d6ff"Tffd700${Te6edf3VENV_DIRTffd700}Ta5d6ff/bin/pythonTa5d6ff" - Ta5d6ff<<PY
import json
import tarfile
import urllib.request
from pathlib import Path

version = "${PYCODEC2_VERSIONTff7b72}Ta5d6ff"
work_dir = Path("Tffd700${Te6edf3WORK_DIRTffd700}Ta5d6ff")
sources_dir = Path("Tffd700${Te6edf3WORK_DIRTffd700}/sourcesTa5d6ff")
sdist_path = work_dir / f"pycodec2-Tff7b72{versionTff7b72}.tar.gzTa5d6ff"

with urllib.request.urlopen(f"https://pypi.org/pypi/pycodec2/Tff7b72{versionTff7b72}/jsonTa5d6ff") as resp:
payload = json.load(resp)

sdist_url = None
for file_entry in payload.get("urlsTa5d6ff", []):
if file_entry.get("packagetypeTa5d6ff") == "sdistTa5d6ff":
sdist_url = file_entry.get("urlTa5d6ff")
break

if not sdist_url:
raise SystemExit(f"No sdist URL found Tff7b72for pycodec2 Tff7b72{versionTff7b72}Ta5d6ff")

urllib.request.urlretrieve(sdist_url, sdist_path)
with tarfile.open(sdist_path, "r:gzTa5d6ff") as tf:
tf.extractall(path=sources_dir)
sdist_path.unlink()
PY

"Tffd700${Te6edf3VENV_DIRTffd700}/bin/pythonTa5d6ff" - <<PY
from pathlib import Path

pyproject = Path("Tffd700${Te6edf3SOURCE_DIRTffd700}/pyproject.tomlTa5d6ff"Ta5d6ff)
text = pyproject.read_text()
text = text.replace('numpy==2.1.*', 'numpy==Tffd700${Te6edf3NUMPY_VERSIONTffd700}Ta5d6ff')
text = text.replace('numpy>=2.00, <3.0.0', 'numpy==Tffd700${Te6edf3NUMPY_VERSIONTffd700}Ta5d6ff')
pyproject.write_text(text)

setup_py = Path(Ta5d6ff"Tffd700${Te6edf3SOURCE_DIRTffd700}/setup.pyTa5d6ff")
setup_text = setup_py.read_text()
if "from pathlib import PathTa5d6ff" not in setup_text:
setup_text = setup_text.replace("import sysTffea00\nTa5d6ff", "import sysTffea00\nfrom pathlib import PathTffea00\nTa5d6ff")
setup_text = setup_text.replace(
'libraries=["libcodec2Ta5d6ff"] if sys.platform == "win32Ta5d6ff" else ["codec2Ta5d6ff"],',
'libraries=["libcodec2Ta5d6ff"] if sys.platform == "win32Ta5d6ff" else [],'
)
if "Te6edf3extra_objectsTff7b72=Tff7b72[Tff7b72] Tff7b72if sys.platform Tff7b72=Tff7b72= Tffea00\"win32Tffea00\"Ta5d6ff" not in setup_text:
setup_text = setup_text.replace(
'libraries=["libcodec2Ta5d6ff"] if sys.platform == "win32Ta5d6ff" else [],',
'libraries=["libcodec2Ta5d6ff"] if sys.platform == "win32Ta5d6ff" else [],\n'
' extra_objects=[] if sys.platform == "win32Ta5d6ff" else [str((Path(__file__).resolve().parent / "pycodec2Ta5d6ff" / "libcodec2.soTa5d6ff"))],'
)
if "class ChaquopyBuildExtTa5d6ff" not in setup_text:
setup_text = setup_text.replace(
"setupTff7b72(Ta5d6ff",
"class ChaquopyBuildExtTff7b72(Cython.Build.build_extTff7b72):Tffea00\nTa5d6ff"
" def build_extensionsTff7b72(selfTff7b72):Tffea00\nTa5d6ff"
" Te6edf3c_file Tff7b72= PathTff7b72(__file__Tff7b72).resolveTff7b72(Tff7b72).parent / Tffea00\"pycodec2Tffea00\" / Tffea00\"pycodec2.cTffea00\"Tffea00\nTa5d6ff"
" Tff7b72if c_file.existsTff7b72(Tff7b72):Tffea00\nTa5d6ff"
" Te6edf3text Tff7b72= c_file.read_textTff7b72(Tff7b72)Tffea00\nTa5d6ff"
" Te6edf3text Tff7b72= text.replaceTff7b72(Tffea00\nTa5d6ff"
" Tffea00\"T8b949e#ifndef CYTHON_NO_PYINIT_EXPORT\",\n"
Ta5d6ff" \"#undef CYTHON_NO_PYINIT_EXPORT\\\\n#ifndef CYTHON_NO_PYINIT_EXPORT\",\n"
Ta5d6ff" )\n"
Ta5d6ff" text = text.replace(\n"
Ta5d6ff" \"#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC\",\n"
Ta5d6ff' \'T8b949e#define __Pyx_PyMODINIT_FUNC __attribute__((visibility("default"))) PyObject *\',\n'
Ta5d6ff" )\n"
Ta5d6ff" c_file.write_text(text)\n"
Ta5d6ff" if sys.platform != \"win32\":\n"
Ta5d6ff" self.compiler.linker_so = [\n"
Ta5d6ff" arg for arg in self.compiler.linker_so\n"
Ta5d6ff" if \"python3\" not in arg and arg != \"-Wl,--no-undefined\"\n"
Ta5d6ff" ]\n"
Ta5d6ff" super().build_extensions()\n\n"
Ta5d6ff"setup("
Tff7b72)
Te6edf3setup_text Tff7b72= setup_text.replaceTff7b72(
Ta5d6ff'cmdclass={"build_ext": Cython.Build.build_ext},',
Ta5d6ff'cmdclass={"build_ext": ChaquopyBuildExt},'
Tff7b72)
setup_py.write_textTff7b72(setup_textTff7b72)

import shutil
import numpy as np
import re

Te6edf3numpy_headers Tff7b72= PathTff7b72(np.get_includeTff7b72(Tff7b72)Tff7b72) / Ta5d6ff"numpy"
Te6edf3vendored_numpy Tff7b72= PathTff7b72(Ta5d6ff"Tffd700${Te6edf3SOURCE_DIRTffd700}Ta5d6ff/pycodec2/numpyTa5d6ff"Tff7b72)
Tff7b72if vendored_numpy.existsTff7b72(Tff7b72):
shutil.rmtreeTff7b72(vendored_numpyTff7b72)
shutil.copytreeTff7b72(numpy_headers, vendored_numpyTff7b72)

Te6edf3include_pattern Tff7b72= re.compileTff7b72(rTa5d6ff'#include\s+<numpy/([^>]+)>'Tff7b72)
Tff7b72for header Tff7b72in vendored_numpy.rglobTff7b72(Ta5d6ff"*.h"Tff7b72):
Te6edf3content Tff7b72= header.read_textTff7b72(Tff7b72)
Te6edf3content Tff7b72= include_pattern.subTff7b72(rTa5d6ff'#include "\1"', contentTff7b72)
header.write_textTff7b72(contentTff7b72)
PY

cat > Ta5d6ff"Tffd700${Te6edf3LIBCODEC2_RECIPE_DIRTffd700}Ta5d6ff/meta.yamlTa5d6ff" Ta5d6ff<<EOF
package:
name: chaquopy-libcodec2
version: "${LIBCODEC2_VERSION}"

source:
git_url: "https://github.com/drowe67/codec2.git"
git_rev: "${LIBCODEC2_VERSION}"

requirements:
build:
- cmake 3.22.1

about:
license_file: COPYING
EOF

cat > Ta5d6ff"Tffd700${Te6edf3LIBCODEC2_RECIPE_DIRTffd700}Ta5d6ff/build.shTa5d6ff" Ta5d6ff<<'EOF'
set -eu

cc src/generate_codebook.c -lm -o src/generate_codebook_host
python3 - <<'PY'
from pathlib import Path

cmake_file = Path("src/CMakeLists.txt")
text = cmake_file.read_text()
old_block = """# when crosscompiling we need a native executable
if(CMAKE_CROSSCOMPILING)
set(CMAKE_DISABLE_SOURCE_CHANGES OFF)
include(ExternalProject)
ExternalProject_Add(codec2_native
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/..
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/codec2_native
BUILD_COMMAND ${CMAKE_COMMAND} --build . --target generate_codebook
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/codec2_native/src/generate_codebook ${CMAKE_CURRENT_BINARY_DIR}
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/generate_codebook
)
add_executable(generate_codebook IMPORTED)
set_target_properties(generate_codebook PROPERTIES
IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/generate_codebook)
add_dependencies(generate_codebook codec2_native)
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
else(CMAKE_CROSSCOMPILING)
# generate_codebook
add_executable(generate_codebook generate_codebook.c)
target_link_libraries(generate_codebook m)
# Make native builds available for cross-compiling.
export(TARGETS generate_codebook
FILE ${CMAKE_BINARY_DIR}/ImportExecutables.cmake)
endif(CMAKE_CROSSCOMPILING)
"""
new_block = """# Use host-native generator to avoid nested cross-compilation recursion.
set(HOST_GENERATE_CODEBOOK ${CMAKE_CURRENT_SOURCE_DIR}/generate_codebook_host)
"""
if old_block not in text:
raise SystemExit("Could not find expected generate_codebook block in CMakeLists.txt")
text = text.replace(old_block, new_block)
text = text.replace("COMMAND generate_codebook", "COMMAND ${HOST_GENERATE_CODEBOOK}")
text = text.replace("DEPENDS generate_codebook ", "DEPENDS ")
cmake_file.write_text(text)

codec2_h = Path("src/codec2.h")
codec2_text = codec2_h.read_text()
codec2_text = codec2_text.replace("#include <codec2/version.h>", '#include "version.h"')
codec2_h.write_text(codec2_text)

Path("src/version.h").write_text(
"#ifndef CODEC2_VERSION_H\n"
"#define CODEC2_VERSION_H\n"
"#define CODEC2_VERSION_MAJOR 1\n"
"#define CODEC2_VERSION_MINOR 2\n"
"#define CODEC2_VERSION_PATCH 0\n"
"#define CODEC2_VERSION \"1.2.0\"\n"
"#endif\n"
)

root_cmake = Path("CMakeLists.txt")
root_text = root_cmake.read_text()
root_text = root_text.replace("add_subdirectory(demo)\n", "")
root_cmake.write_text(root_text)
PY

mkdir -p build-chaquopy
cd build-chaquopy
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="$PREFIX" \
-DBUILD_SHARED_LIBS=ON
mkdir -p src
cp -f ../src/defines.h src/defines.h
make -j "$CPU_COUNT"
make install
mkdir -p "$PREFIX/include/codec2"
cp -f ../src/version.h "$PREFIX/include/codec2/version.h"

rm -f "$PREFIX"/lib/*.a || true
rm -rf "$PREFIX"/lib/cmake || true
rm -rf "$PREFIX"/share || true
EOF
chmod +x Ta5d6ff"Tffd700${Te6edf3LIBCODEC2_RECIPE_DIRTffd700}Ta5d6ff/build.shTa5d6ff"

cat > Ta5d6ff"Tffd700${Te6edf3RECIPE_DIRTffd700}Ta5d6ff/meta.yamlTa5d6ff" Ta5d6ff<<EOF
package:
name: pycodec2
version: "${PYCODEC2_VERSION}"

source:
path: "${SOURCE_DIR}"

requirements:
build:
- cython 3.0.11
host:
- chaquopy-libcodec2 ${LIBCODEC2_VERSION}
- python

about:
license_file: LICENSE
EOF

Tffa657pushd Ta5d6ff"Tffd700${Te6edf3PYPIDIRTffd700}Ta5d6ff" >/dev/null
Tff7b72for abi Tff7b72in Tffd700${Te6edf3ABI_LISTTb4b4b4//,/ Tffd700}Tb4b4b4; Tff7b72do
Te6edf3abi_tagTff7b72=Ta5d6ff"Tffd700${Te6edf3abiTb4b4b4//-/_Tffd700}Ta5d6ff"

Tffa657echo Ta5d6ff"Ta5d6ffBuilding chaquopy-libcodec2 Tffd700${Te6edf3LIBCODEC2_VERSIONTffd700}Ta5d6ff for Tffd700${Te6edf3abiTffd700}Ta5d6ff"
Ta5d6ff"Tffd700${Te6edf3VENV_DIRTffd700}Ta5d6ff/bin/pythonTa5d6ff" Ta5d6ff"Tffd700${Te6edf3PYPIDIRTffd700}Ta5d6ff/build-wheel.pyTa5d6ff" Tffea00\
--python Ta5d6ff"Tffd700${Te6edf3PYTHON_MINORTffd700}Ta5d6ff" Tffea00\
--api-level Ta5d6ff"Tffd700${Te6edf3API_LEVELTffd700}Ta5d6ff" Tffea00\
--abi Ta5d6ff"Tffd700${Te6edf3abiTffd700}Ta5d6ff" Tffea00\
Ta5d6ff"Tffd700${Te6edf3LIBCODEC2_RECIPE_DIRTffd700}Ta5d6ff"

Te6edf3LIBCODEC2_PREFIXTff7b72=Ta5d6ff"Tffd700${Te6edf3LIBCODEC2_RECIPE_DIRTffd700}Ta5d6ff/build/Tffd700${Te6edf3LIBCODEC2_VERSIONTffd700}Ta5d6ff/py3-none-android_Tffd700${Te6edf3API_LEVELTffd700}Ta5d6ff_Tffd700${Te6edf3abi_tagTffd700}Ta5d6ff/prefix/chaquopyTa5d6ff"
Tff7b72if Tff7b72[Tff7b72[ ! -f Ta5d6ff"Tffd700${Te6edf3LIBCODEC2_PREFIXTffd700}Ta5d6ff/lib/libcodec2.soTa5d6ff" Tff7b72]Tff7b72]Tb4b4b4; Tff7b72then
Tffa657echo Ta5d6ff"Ta5d6ffMissing libcodec2 output for Tffd700${Te6edf3abiTffd700}Ta5d6ff: Tffd700${Te6edf3LIBCODEC2_PREFIXTffd700}Ta5d6ff/lib/libcodec2.soTa5d6ff" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72fi
mkdir -p Ta5d6ff"Tffd700${Te6edf3SOURCE_DIRTffd700}Ta5d6ff/pycodec2/codec2Ta5d6ff"
cp -f Ta5d6ff"Tffd700${Te6edf3LIBCODEC2_PREFIXTffd700}Ta5d6ff/include/codec2/codec2.hTa5d6ff" Ta5d6ff"Tffd700${Te6edf3SOURCE_DIRTffd700}Ta5d6ff/pycodec2/codec2/codec2.hTa5d6ff"
cp -f Ta5d6ff"Tffd700${Te6edf3LIBCODEC2_PREFIXTffd700}Ta5d6ff/include/codec2/version.hTa5d6ff" Ta5d6ff"Tffd700${Te6edf3SOURCE_DIRTffd700}Ta5d6ff/pycodec2/codec2/version.hTa5d6ff"
cp -f Ta5d6ff"Tffd700${Te6edf3LIBCODEC2_PREFIXTffd700}Ta5d6ff/lib/libcodec2.soTa5d6ff" Ta5d6ff"Tffd700${Te6edf3SOURCE_DIRTffd700}Ta5d6ff/pycodec2/libcodec2.soTa5d6ff"
sed -i Ta5d6ff's|#include <codec2/version.h>|#include "version.h"|' Ta5d6ff"Tffd700${Te6edf3SOURCE_DIRTffd700}Ta5d6ff/pycodec2/codec2/codec2.hTa5d6ff"

Te6edf3PYCODEC2_PREFIXTff7b72=Ta5d6ff"Tffd700${Te6edf3RECIPE_DIRTffd700}Ta5d6ff/build/Tffd700${Te6edf3PYCODEC2_VERSIONTffd700}Ta5d6ff/Tffd700${Te6edf3PYTHON_ABI_TAGTffd700}Ta5d6ff-Tffd700${Te6edf3PYTHON_ABI_TAGTffd700}Ta5d6ff-android_Tffd700${Te6edf3API_LEVELTffd700}Ta5d6ff_Tffd700${Te6edf3abi_tagTffd700}Ta5d6ff/requirements/chaquopyTa5d6ff"
Te6edf3PY_INCLUDE_DIRTff7b72=Ta5d6ff"Tffd700${Te6edf3PYCODEC2_PREFIXTffd700}Ta5d6ff/include/pythonTffd700${Te6edf3PYTHON_MINORTffd700}Ta5d6ff"
mkdir -p Ta5d6ff"Tffd700${Te6edf3PY_INCLUDE_DIRTffd700}Ta5d6ff/numpyTa5d6ff" Ta5d6ff"Tffd700${Te6edf3PY_INCLUDE_DIRTffd700}Ta5d6ff/codec2Ta5d6ff" Ta5d6ff"Tffd700${Te6edf3PYCODEC2_PREFIXTffd700}Ta5d6ff/libTa5d6ff"
cp -f Ta5d6ff"Tffd700${Te6edf3SOURCE_DIRTffd700}Ta5d6ff/pycodec2/codec2/codec2.hTa5d6ff" Ta5d6ff"Tffd700${Te6edf3PY_INCLUDE_DIRTffd700}Ta5d6ff/codec2/codec2.hTa5d6ff"
cp -f Ta5d6ff"Tffd700${Te6edf3SOURCE_DIRTffd700}Ta5d6ff/pycodec2/codec2/version.hTa5d6ff" Ta5d6ff"Tffd700${Te6edf3PY_INCLUDE_DIRTffd700}Ta5d6ff/codec2/version.hTa5d6ff"
cp -rf Ta5d6ff"Tffd700${Te6edf3SOURCE_DIRTffd700}Ta5d6ff/pycodec2/numpy/.Ta5d6ff" Ta5d6ff"Tffd700${Te6edf3PY_INCLUDE_DIRTffd700}Ta5d6ff/numpy/Ta5d6ff"
cp -f Ta5d6ff"Tffd700${Te6edf3SOURCE_DIRTffd700}Ta5d6ff/pycodec2/libcodec2.soTa5d6ff" Ta5d6ff"Tffd700${Te6edf3PYCODEC2_PREFIXTffd700}Ta5d6ff/lib/libcodec2.soTa5d6ff"

Tffa657echo Ta5d6ff"Ta5d6ffBuilding pycodec2 Tffd700${Te6edf3PYCODEC2_VERSIONTffd700}Ta5d6ff for Tffd700${Te6edf3abiTffd700}Ta5d6ff"
Te6edf3C_INCLUDE_PATHTff7b72=Ta5d6ff"Tffd700${Te6edf3PY_INCLUDE_DIRTffd700}Ta5d6ff" Te6edf3CPLUS_INCLUDE_PATHTff7b72=Ta5d6ff"Tffd700${Te6edf3PY_INCLUDE_DIRTffd700}Ta5d6ff" Te6edf3LIBRARY_PATHTff7b72=Ta5d6ff"Tffd700${Te6edf3PYCODEC2_PREFIXTffd700}Ta5d6ff/libTa5d6ff" Ta5d6ff"Tffd700${Te6edf3VENV_DIRTffd700}Ta5d6ff/bin/pythonTa5d6ff" Ta5d6ff"Tffd700${Te6edf3PYPIDIRTffd700}Ta5d6ff/build-wheel.pyTa5d6ff" Tffea00\
--python Ta5d6ff"Tffd700${Te6edf3PYTHON_MINORTffd700}Ta5d6ff" Tffea00\
--api-level Ta5d6ff"Tffd700${Te6edf3API_LEVELTffd700}Ta5d6ff" Tffea00\
--abi Ta5d6ff"Tffd700${Te6edf3abiTffd700}Ta5d6ff" Tffea00\
Ta5d6ff"Tffd700${Te6edf3RECIPE_DIRTffd700}Ta5d6ff"
Tff7b72done
Tffa657popd >/dev/null

mkdir -p Ta5d6ff"Tffd700${Te6edf3OUT_DIRTffd700}Ta5d6ff"
cp -f Ta5d6ff"Tffd700${Te6edf3PYPIDIRTffd700}Ta5d6ff/dist/chaquopy-libcodec2Ta5d6ff"/chaquopy_libcodec2-Ta5d6ff"Tffd700${Te6edf3LIBCODEC2_VERSIONTffd700}Ta5d6ff"-*.whl Ta5d6ff"Tffd700${Te6edf3OUT_DIRTffd700}Ta5d6ff/Ta5d6ff"
cp -f Ta5d6ff"Tffd700${Te6edf3PYPIDIRTffd700}Ta5d6ff/dist/pycodec2Ta5d6ff"/pycodec2-Ta5d6ff"Tffd700${Te6edf3PYCODEC2_VERSIONTffd700}Ta5d6ff"-*.whl Ta5d6ff"Tffd700${Te6edf3OUT_DIRTffd700}Ta5d6ff/Ta5d6ff"

Tff7b72else
Tffa657echo Ta5d6ff"Skipping pycodec2/chaquopy-libcodec2 builds (--only-recipes set)"
Tff7b72fi

mkdir -p Ta5d6ff"Tffd700${Te6edf3OUT_DIRTffd700}Ta5d6ff"

Tff7b72if Tff7b72[Tff7b72[ Ta5d6ff"Tffd700${Te6edf3PATCH_LXSTTffd700}Ta5d6ff" Tff7b72=Tff7b72= Ta5d6ff"1" Tff7b72&& -z Ta5d6ff"Tffd700${Te6edf3ONLY_RECIPESTffd700}Ta5d6ff" Tff7b72]Tff7b72]Tb4b4b4; Tff7b72then
Te6edf3TMP_DIRTff7b72=Ta5d6ff"Tff7b72$(mktemp -dTff7b72)Ta5d6ff"
Tffa657trap Ta5d6ff'rm -rf "${TMP_DIR}"' EXIT

Ta5d6ff"Tffd700${Te6edf3VENV_DIRTffd700}Ta5d6ff/bin/pipTa5d6ff" download Tffea00\
--only-binaryTff7b72=:all: Tffea00\
--no-deps Tffea00\
Ta5d6ff"Ta5d6fflxst==Tffd700${Te6edf3LXST_VERSIONTffd700}Ta5d6ff" Tffea00\
--dest Ta5d6ff"Tffd700${Te6edf3TMP_DIRTffd700}Ta5d6ff" Tffea00\
--index-url https://pypi.org/simple

Te6edf3LXST_WHEELTff7b72=Ta5d6ff"Tff7b72$(ls Ta5d6ff"Tffd700${Te6edf3TMP_DIRTffd700}Ta5d6ff"/lxst-Ta5d6ff"Tffd700${Te6edf3LXST_VERSIONTffd700}Ta5d6ff"-py3-none-any.whlTff7b72)Ta5d6ff"
Te6edf3PATCHED_LXST_WHEELTff7b72=Ta5d6ff"Tffd700${Te6edf3OUT_DIRTffd700}Ta5d6ff/lxst-Tffd700${Te6edf3LXST_VERSIONTffd700}Ta5d6ff-py3-none-any.whlTa5d6ff"

Ta5d6ff"Tffd700${Te6edf3VENV_DIRTffd700}Ta5d6ff/bin/pythonTa5d6ff" - Ta5d6ff<<PY
import zipfile
from pathlib import Path

src = Path("${LXST_WHEEL}")
dst = Path("${PATCHED_LXST_WHEEL}")
patched_codecs_init = """from .Codec import CodecError as CodecError
from .Codec import Codec as Codec
from .Codec import Null as Null
from .Raw import Raw as Raw
from .Opus import Opus as Opus

_CODEC2_IMPORT_ERROR = None
try:
from .Codec2 import Codec2 as Codec2
except Exception as _codec2_exc:
Codec2 = None
_CODEC2_IMPORT_ERROR = _codec2_exc

NULL = 0xFF
RAW = 0x00
OPUS = 0x01
CODEC2 = 0x02

def _raise_codec2_unavailable():
if _CODEC2_IMPORT_ERROR is not None:
raise CodecError(f"Codec2 backend unavailable: {_CODEC2_IMPORT_ERROR}")
raise CodecError("Codec2 backend unavailable")

def codec_header_byte(codec):
if codec == Raw:
return RAW.to_bytes()
elif codec == Opus:
return OPUS.to_bytes()
elif Codec2 is not None and codec == Codec2:
return CODEC2.to_bytes()

raise TypeError(f"No header mapping for codec type {codec}")

def codec_type(header_byte):
if header_byte == RAW:
return Raw
elif header_byte == OPUS:
return Opus
elif header_byte == CODEC2:
if Codec2 is None:
_raise_codec2_unavailable()
return Codec2
"""

with zipfile.ZipFile(src, "r") as zin, zipfile.ZipFile(dst, "w", compression=zipfile.ZIP_DEFLATED) as zout:
for item in zin.infolist():
data = zin.read(item.filename)
if item.filename == "LXST/Codecs/__init__.py":
data = patched_codecs_init.encode("utf-8")
elif item.filename.endswith(".dist-info/METADATA"):
text = data.decode("utf-8")
text = text.replace("Requires-Dist: numpy>=2.3.4", "Requires-Dist: numpy==${NUMPY_VERSIONTff7b72}Ta5d6ff")
text = text.replace("Requires-Dist: cffi>Tff7b72=T79c0ff2.0.0Ta5d6ff", "Requires-Dist: Te6edf3cffiTff7b72=Tff7b72=T79c0ff1.15.1Ta5d6ff")
data = text.encode("utf-8Ta5d6ff")
zout.writestr(item, data)
PY
fi

CUSTOM_RECIPES_DIR="Tffd700${Te6edf3ROOT_DIRTffd700}/android/chaquopy-recipesTa5d6ff"
ONLY_RECIPES_FILTER="Ta5d6ff"
if [[ -n "Tffd700${Te6edf3ONLY_RECIPESTffd700}Ta5d6ff" ]]; then
ONLY_RECIPES_FILTER=" Tffd700${Te6edf3ONLY_RECIPESTb4b4b4//,/ Tffd700} Ta5d6ff"
fi
if [[ -d "Tffd700${Te6edf3CUSTOM_RECIPES_DIRTffd700}Ta5d6ff" ]]; then
echo "Building custom Android recipes from Tffd700${Te6edf3CUSTOM_RECIPES_DIRTffd700}Ta5d6ff"
for RECIPE_SRC in "Tffd700${Te6edf3CUSTOM_RECIPES_DIRTffd700}Ta5d6ff"/*; do
if [[ ! -d "Tffd700${Te6edf3RECIPE_SRCTffd700}Ta5d6ff" ]]; then
continue
fi

RECIPE_NAME="Tff7b72$(basename Ta5d6ff"Tffd700${Te6edf3RECIPE_SRCTffd700}Ta5d6ff"Tff7b72)Ta5d6ff"
if [[ -n "Tffd700${Te6edf3ONLY_RECIPES_FILTERTffd700}Ta5d6ff" && "Tffd700${Te6edf3ONLY_RECIPES_FILTERTffd700}Ta5d6ff" != *" Tffd700${Te6edf3RECIPE_NAMETffd700} Ta5d6ff"* ]]; then
echo "Skipping recipe Tffd700${Te6edf3RECIPE_NAMETffd700} Tff7b72(not Tff7b72in --only-recipes listTff7b72)Ta5d6ff"
continue
fi
RECIPE_DST="Tffd700${Te6edf3PYPIDIRTffd700}/packages/Tffd700${Te6edf3RECIPE_NAMETffd700}-localTa5d6ff"
rm -rf "Tffd700${Te6edf3RECIPE_DSTTffd700}Ta5d6ff"
mkdir -p "Tffd700${Te6edf3RECIPE_DSTTffd700}Ta5d6ff"
cp -a "Tffd700${Te6edf3RECIPE_SRCTffd700}/.Ta5d6ff" "Tffd700${Te6edf3RECIPE_DSTTffd700}/Ta5d6ff"

read -r PACKAGE_NAME PACKAGE_VERSION < <("Tffd700${Te6edf3VENV_DIRTffd700}/bin/pythonTa5d6ff" - <<PY
from pathlib import Path
import re
meta = Path("Tffd700${Te6edf3RECIPE_DSTTffd700}/meta.yamlTa5d6ff").read_text()
name = re.search(r'(?m)^\\s*name:\\s*"?Tff7b72(.*?Tff7b72)Ta5d6ff"Ta5d6ff?\\s*$Ta5d6ff', meta)
version = re.search(r'(?m)^\\s*version:\\s*Ta5d6ff"?Tff7b72(.*?Tff7b72)Ta5d6ff"Ta5d6ff?\\s*$Ta5d6ff', meta)
if not name or not version:
raise SystemExit(Ta5d6ff"Failed parsing name/version from meta.yamlTa5d6ff")
print(name.group(1), version.group(1))
PY
)

echo "Building Tffd700${Te6edf3PACKAGE_NAMETffd700} Tffd700${Te6edf3PACKAGE_VERSIONTffd700} from recipe Tffd700${Te6edf3RECIPE_NAMETffd700}Ta5d6ff"
Ta5d6ff for abi in Tffd700${Te6edf3ABI_LISTTb4b4b4//,/ Tffd700}Ta5d6ff; do
abi_tag=Ta5d6ff"Tffd700${Te6edf3abiTb4b4b4//-/_Tffd700}Ta5d6ff"
if [[ "Tffd700${Te6edf3PACKAGE_NAMETffd700}Ta5d6ff" == "cffiTa5d6ff" ]]; then
cache_chaquopy_libffi_for_abi "Tffd700${Te6edf3abiTffd700}Ta5d6ff"
fi
echo "Building Tffd700${Te6edf3PACKAGE_NAMETffd700} Tffd700${Te6edf3PACKAGE_VERSIONTffd700} Tff7b72for Tffd700${Te6edf3abiTffd700}Ta5d6ff"
"Tffd700${Te6edf3VENV_DIRTffd700}/bin/pythonTa5d6ff" "Tffd700${Te6edf3PYPIDIRTffd700}/build-wheel.pyTa5d6ff" \
--python "Tffd700${Te6edf3PYTHON_MINORTffd700}Ta5d6ff" \
--api-level "Tffd700${Te6edf3API_LEVELTffd700}Ta5d6ff" \
--abi "Tffd700${Te6edf3abiTffd700}Ta5d6ff" \
"Tffd700${Te6edf3RECIPE_DSTTffd700}Ta5d6ff"

WHEEL_GLOB="Tffd700${Te6edf3PYPIDIRTffd700}/dist/Tffd700${Te6edf3PACKAGE_NAMETffd700}Ta5d6ff"/*android_"Tffd700${Te6edf3API_LEVELTffd700}Ta5d6ff"_"Tffd700${Te6edf3abi_tagTffd700}Ta5d6ff"Ta5d6ff.whl
if ! ls Tffd700${Te6edf3WHEEL_GLOBTffd700}Ta5d6ff >/dev/null 2>&1; then
echo Ta5d6ff"Missing wheel output Tff7b72for Tffd700${Te6edf3PACKAGE_NAMETffd700} Tffd700${Te6edf3PACKAGE_VERSIONTffd700} Tffd700${Te6edf3abiTffd700}Ta5d6ff"Ta5d6ff >&2
exit 1
fi
cp -f Tffd700${Te6edf3WHEEL_GLOBTffd700}Ta5d6ff Ta5d6ff"Tffd700${Te6edf3OUT_DIRTffd700}/Ta5d6ff"
done

if [[ "Tffd700${Te6edf3PACKAGE_NAMETffd700}Ta5d6ff" == "cryptographyTa5d6ff" ]]; then
"Tffd700${Te6edf3VENV_DIRTffd700}/bin/pythonTa5d6ff" - <<PY
import zipfile
from pathlib import Path

version = "Tffd700${Te6edf3PACKAGE_VERSIONTffd700}Ta5d6ff"
out_dir = Path("Tffd700${Te6edf3OUT_DIRTffd700}Ta5d6ff")
for wheel in sorted(out_dir.glob(f"cryptography-Tff7b72{versionTff7b72}-*.whlTa5d6ff")):
tmp = wheel.with_suffix(".tmp.whlTa5d6ff")
with zipfile.ZipFile(wheel, "rTa5d6ff") as zin, zipfile.ZipFile(tmp, "wTa5d6ff", compression=zipfile.ZIP_DEFLATED) as zout:
for item in zin.infolist():
data = zin.read(item.filename)
if item.filename.endswith(".dist-info/METADATATa5d6ff"):
text = data.decode("utf-8Ta5d6ff")
text = text.replace("Requires-Dist: cffi>Tff7b72=T79c0ff2.0.0 Tb4b4b4;Ta5d6ff", "Requires-Dist: cffi>Tff7b72=T79c0ff1.15.1 Tb4b4b4;Ta5d6ff")
data = text.encode("utf-8Ta5d6ff")
zout.writestr(item, data)
tmp.replace(wheel)
PY
fi
done
fi

echo "Done.Ta5d6ff"
echo "Built wheels Tff7b72in: Tffd700${Te6edf3OUT_DIRTffd700}Ta5d6ff"
ls -1 "Tffd700${Te6edf3OUT_DIRTffd700}Ta5d6ff"Ta5d6ff | sort


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────